package Network

import (
	"bufio"
	"fmt"
	"net"
)

// Define Client Receiver
type ClientReceiver interface {
	onConnected()
	onDisConnected()
	heartBeat()

	onReceiveMessage(str string)
}

const (
	Unknow = itoa
	Connected
	Disconnected
	Connecting
)

type Client struct {
	// Used for Servce
	ID int

	Connection net.Conn

	// Close Channel
	closeChan chan int

	receiver  *ClientReceiver

	// Connect Status
	Status  int
}

func NewClient(ip string, port int, receiver *ClientReceiver) Client {
	var client Client

	// Connection server
	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", ip, port))
	if err != nil {
		panic(err)
	}
	client.Connection = conn

	client.ID = 0

	client.closeChan = make(chan int)

	client.receiver = receiver

	client.Status = Connecting

	// read message by goroution
	client.readMessage()

	// Notify receiver connected.
	client.receiver.onConnected()

	return client
}

func (client Client) WriteString(str string) {
	str += "\n"
	fmt.Fprint(client.Conn, str)
}

// Create goroutine to read string
func (client Client) readMessage() {
	go func() {
		for {
			select {
			// Check close.
			case <-client.closeChan:
				client.Close()
				return
			default:
				msg, err := bufio.NewReader(client.Conn).ReadString('\n')
				if err != nil {
					client.Close()
					return
				}

				fmt.Println("[Client::readMessage]", msg)
				client.receiver.onReceiveMessage(msg)
			}
		}
	}()
}

// Notify Client shutdown
func (client Client) Close() {
	// client.closeChan <- 1
	client.Conn.Close()

	client.receiver.onDisConnected()
}
